package com.symone.webcms.controller;

import com.symone.webcms.common.ResultCode;
import com.symone.webcms.controller.base.BaseController;
import com.symone.webcms.model.LoginLog;
import com.symone.webcms.model.User;
import com.symone.webcms.model.base.ResultMessage;
import com.symone.webcms.model.vo.UserVO;
import io.swagger.annotations.Api;
import nl.bitwalker.useragentutils.UserAgent;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Enumeration;

@Controller
@Api(value = "LoginController",description = "系统登录管理")
public class LoginController extends BaseController{

    /**
     * 登陆
     */
    @RequestMapping(value = "/doLogin", method = RequestMethod.POST)
    @ResponseBody
    public ResultMessage doLogin(String name, String password, Long formcheck, String remember) {

        // 从SecurityUtils里边创建一个 subject
        Subject subject = SecurityUtils.getSubject();
        // 在认证提交前准备 token（令牌）
        UsernamePasswordToken token = new UsernamePasswordToken(name, password);
        token.setRememberMe( remember!=null&&remember.equals("on") );

        HttpServletRequest request = getRequest();
        String userAgentString = request.getHeader("User-Agent");
        UserAgent userAgent = UserAgent.parseUserAgentString(userAgentString);
        LoginLog loginLog = new LoginLog();

        loginLog.setBrowser(userAgent.getBrowser() + " " + userAgent.getBrowserVersion());
        loginLog.setIpAddress(request.getRemoteAddr());
        loginLog.setOs(userAgent.getOperatingSystem().getName());
        loginLog.setDevice(userAgent.getOperatingSystem().getDeviceType().getName());
        loginLog.setUserAgent(userAgentString);
        loginLog.setUrl(request.getRequestURL().toString());

        StringBuilder sb = new StringBuilder();
        Enumeration<String> enu = request.getParameterNames();
        while (enu.hasMoreElements()) {
            String key = (String) enu.nextElement();
            sb.append( key + "=" + request.getParameter(key));
            if(enu.hasMoreElements()){
                sb.append( ",");
            }
        }
        loginLog.setParams(sb.toString());
        loginLog.setLoginName(name);
        loginLog.setLoginPassword(password);

        if( !checkMvcForm(formcheck) ){
            return ResultMessage.fail(ResultCode.InvalidLoginType);
        }

        // 执行认证登陆
        try {
            subject.login(token);
            UserVO loginUser = (UserVO) subject.getPrincipal();
            logger.info("Current User : " + loginUser);

            User user = new User();
            user.setId(loginUser.getId());
            user.setLastLoginIp(request.getRemoteAddr());
            user.setLastLoginTime(new Date());
            user.setLoginCount(loginUser.getLoginCount() + 1);
            user.updateById();

            loginLog.setState(ResultCode.SUCCESS.getCode());
            loginLog.setMemo("Okay");
            loginLog.insert();

        } catch ( UnknownAccountException uae ) {
            logger.info( "login failed! UnknownAccountException: " + uae.getMessage());
            token.clear();
            loginLog.setState(ResultCode.UnknownAccountError.getCode());
            loginLog.setMemo(ResultCode.UnknownAccountError.getMsg() + "[Exception] UnknownAccountException: " + uae.getMessage());
            loginLog.insert();
            return ResultMessage.fail(ResultCode.UnknownAccountError,uae);
        } catch ( IncorrectCredentialsException ice ) {
            logger.info( "login failed! IncorrectCredentialsException: " + ice.getMessage());
            token.clear();
            loginLog.setState(ResultCode.IncorrectPasswordError.getCode());
            loginLog.setMemo(ResultCode.IncorrectPasswordError.getMsg() + "[Exception] IncorrectCredentialsException: " + ice.getMessage());
            loginLog.insert();
            return ResultMessage.fail(ResultCode.IncorrectPasswordError,ice);
        } catch ( LockedAccountException lae ) {
            logger.info( "login failed! LockedAccountException: " + lae.getMessage());
            token.clear();
            loginLog.setState(ResultCode.LockedAccountError.getCode());
            loginLog.setMemo(ResultCode.LockedAccountError.getMsg() + "[Exception] LockedAccountException: " + lae.getMessage());
            loginLog.insert();
            return ResultMessage.fail(ResultCode.LockedAccountError,lae);
        } catch ( ExcessiveAttemptsException eae ) {
            logger.info( "login failed! ExcessiveAttemptsException: " + eae.getMessage());
            token.clear();
            loginLog.setState(ResultCode.ExcessiveAttemptsError.getCode());
            loginLog.setMemo(ResultCode.ExcessiveAttemptsError.getMsg() + "[Exception] ExcessiveAttemptsException: " + eae.getMessage());
            loginLog.insert();
            return ResultMessage.fail(ResultCode.ExcessiveAttemptsError,eae);
        } catch ( AuthenticationException ae) {
            logger.info( "login failed! AuthenticationException: " + ae.getMessage());
            token.clear();
            loginLog.setState(ResultCode.AuthenticationError.getCode());
            loginLog.setMemo(ResultCode.AuthenticationError.getMsg() + "[Exception] AuthenticationException: " + ae.getMessage());
            loginLog.insert();
            return ResultMessage.fail(ResultCode.AuthenticationError,ae);
        }

        //根据权限，指定返回数据
        return ResultMessage.success("登入成功");
    }
}
